home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2003 November A / PCWK1103A.iso / ABBYY FineReader 7.0 PRO / data1.cab / pdf_main.ps < prev    next >
Text File  |  2002-10-23  |  24KB  |  807 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdf_main.ps,v 1.35.2.2 2002/04/02 13:57:27 mpsuzuki Exp $
  14. % pdf_main.ps
  15. % PDF file- and page-level operations.
  16.  
  17. % ATAPY changes at 23.10.2002. Comments about changes started with string "(ATAPY changes)"
  18.  
  19. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  20. .currentglobal true .setglobal
  21. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  22. pdfdict begin
  23.  
  24. % Patch in an obsolete variable used by some third-party software.
  25. /#? false def
  26.  
  27. % Test whether the current output device handles pdfmark.
  28. /.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
  29. /.writepdfmarks {    % - .writepdfmarks <bool>
  30.   currentdevice //.writepdfmarkdict .getdeviceparams
  31.   mark eq { false } { pop pop true } ifelse
  32.   systemdict /DOPDFMARKS known or 
  33. } bind def
  34.  
  35. % For simplicity, we use a single interpretation dictionary for all
  36. % PDF graphics execution, even though this is too liberal.
  37. /pdfopdict mark
  38.   objopdict { } forall
  39.   drawopdict { } forall
  40.   /endstream { exit } bind
  41.   (%%EOF) cvn { exit } bind        % for filters
  42.     % PDF 1.1 operators
  43.   /BX { /BXlevel BXlevel 1 add store } bind
  44.   /EX { /BXlevel BXlevel 1 sub store } bind
  45.   /PS { cvx exec } bind
  46.     % PDF 1.2 operators
  47.   /BMC { pop } bind
  48.   /BDC { pop pop } bind
  49.   /EMC { }
  50.   /MP { pop } bind
  51.   /DP { pop pop } bind
  52. .dicttomark readonly def
  53.  
  54. % ======================== Main program ======================== %
  55.  
  56. end            % pdfdict
  57. userdict begin
  58.  
  59. /defaultfontname /Times-Roman def
  60.  
  61. % Make sure the registered encodings are loaded, so we don't run the risk
  62. % that some of the indices for their names will overflow the packed
  63. % representation.  (Yes, this is a hack.)
  64. SymbolEncoding pop
  65. DingbatsEncoding pop
  66.  
  67. % Redefine 'run' so it recognizes PDF files.
  68. systemdict begin
  69. /.runps /run load def
  70. /runpdfstring 50 string def        % length is arbitrary
  71.  
  72. % (ATAPY changes) Some PDF-creators produce PDF-s starting with empty line
  73. /skipEmptyLine { % <file> skipEmptyLine <file>
  74.   dup (  ) .peekstring {
  75.     (\r\n) eq {
  76.         dup (  ) readstring pop pop
  77.     } if
  78.   } if
  79. } bind def
  80. % (End of ATAPY changes)
  81.  
  82. /run {
  83.   dup type /filetype ne { (r) file } if
  84.   skipEmptyLine % (ATAPY changes)
  85.   dup ( ) .peekstring {
  86.     (%) eq {
  87.       dup (  ) .peekstring {
  88.     (%P) eq {
  89.       dup //runpdfstring {
  90.         % Some invalid files might have extra-long first lines....
  91.         { readline } .internalstopped not { pop pop exit } if
  92.         pop =string
  93.       } loop
  94.       //runpdfstring (%PDF-) anchorsearch {
  95.         pop pop runpdf
  96.       } {
  97.         pop cvx .runexec
  98.       } ifelse
  99.     } {
  100.       cvx .runps
  101.     } ifelse
  102.       } {
  103.     closefile
  104.       } ifelse
  105.     } {
  106.       cvx .runps
  107.     } ifelse
  108.   } {
  109.     closefile
  110.   } ifelse
  111. } bind odef
  112. currentdict /runpdfstring .undef
  113.  
  114. /runpdf            % <file> runpdf -
  115.  { userdict begin
  116.    /Page# null def
  117.    /Page null def
  118.    /DSCPageCount 0 def
  119.    /PDFSave null def
  120.    GS_PDF_ProcSet begin
  121.    pdfdict begin
  122.    pdfopen begin
  123.    Trailer /Root oget /Pages oget /CropBox knownoget
  124.     { mark /CropBox 3 -1 roll /PAGES pdfmark
  125.     }
  126.    if
  127.    /FirstPage where 
  128.     { pop FirstPage dup pdfpagecount gt
  129.       { (\nRequested FirstPage is greater than the number of pages in the file: ) print
  130.         pdfpagecount = flush
  131.       } if
  132.     } {
  133.       1
  134.     } ifelse
  135.    1
  136.    /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
  137.    2 index 1 index gt
  138.     { (   No pages will be processed \(FirstPage > LastPage\).) = flush }
  139.     { QUIET not
  140.       { (Processing pages ) print 2 index =only ( through ) print dup =only
  141.         (.) = flush
  142.       }
  143.      if
  144.     }
  145.    ifelse
  146.     { dup /Page# exch store
  147.       QUIET not { (Page ) print dup == flush } if
  148.       pdfgetpage pdfshowpage
  149.     } for
  150.    currentdict pdfclose
  151.    end            % temporary dict
  152.    end            % pdfdict
  153.    end            % userdict
  154.  } bind def
  155. end            % systemdict
  156. % Redefine the procedure that the C code uses for running piped input.
  157. % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
  158. /.runstdin {
  159.   { (%stdin) run } execute0
  160. } bind def
  161.  
  162. end            % userdict
  163. pdfdict begin
  164.  
  165. % ======================== File parsing ======================== %
  166.  
  167. % Read the cross-reference and trailer sections.
  168.  
  169. /traileropdict mark
  170.   (<<) cvn { mark } bind
  171.   (>>) cvn /.dicttomark load
  172.   ([) cvn { mark } bind        % ditto
  173.   (]) cvn dup load
  174. %  /true true        % see .pdfexectoken in pdf_base.ps
  175. %  /false false        % ibid.
  176. %  /null null        % ibid.
  177.   /R { /resolveR cvx 3 packedarray cvx } bind    % see Objects below
  178.   /startxref /exit load
  179. .dicttomark readonly def
  180.  
  181. % Because of EOL conversion, lines with fixed contents might be followed
  182. % by one or more blanks.
  183. /lineeq            % <filestr> <conststr> lineeq <bool>
  184.  { anchorsearch
  185.     { pop { ( ) anchorsearch not { () eq exit } if pop } loop }
  186.     { pop false }
  187.    ifelse
  188.  } bind def
  189. /linene { lineeq not } bind def
  190.  
  191. % Read (mostly scan) the cross-reference table.
  192. /readxref        % <pos> readxref <trailerdict>
  193.  { PDFoffset add PDFfile exch setfileposition
  194.         % In some PDF files, this position actually points to
  195.         % white space before the xref line.  Skip over this here.
  196.    { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop
  197.    } loop
  198.    PDFfile exch setfileposition
  199.         % The PDF specification says that the 'xref' must be on a line
  200.         % by itself. The code here formerly used readline and linene to
  201.         % check this. However, Acrobat Reader only requires the line to
  202.         % begin with 'xref', and there are enough applications producing
  203.         % non-compliant PDF files that we have to do this too.
  204.    PDFfile pdfstring 0 4 getinterval readstring pop
  205.    (xref) ne { /readxref cvx /syntaxerror signalerror } if
  206.         % Store the xref table entry position for each object.
  207.         % We only need to read the run headers, not every entry.
  208.     { PDFfile token pop        % first object # or trailer
  209.       dup /trailer eq { pop exit } if
  210.       PDFfile pdfstring readline pop
  211.       token pop            % entry count
  212.       exch pop exch
  213.         % This section might be adding new objects:
  214.         % ensure that Objects and Generations are big enough.
  215.         % Stack: count obj#
  216.       2 copy add growPDFobjects
  217.       PDFfile fileposition 3 -1 roll
  218.        { Objects 2 index lget null eq    % later update might have set it
  219.       { Objects 2 index 2 index cvx lput }
  220.          if exch 1 add exch 20 add
  221.        }
  222.       repeat PDFfile exch setfileposition pop
  223.     } loop
  224.    count /pdfemptycount exch def
  225.    PDFfile traileropdict .pdfrun
  226.  } bind def
  227.  
  228. % Open a PDF file and read the header, trailer, and cross-reference.
  229. /pdfopen {        % <file> pdfopen <dict>
  230.   pdfopenfile begin
  231.   pdfopencache
  232.   .writepdfmarks {
  233.     % Copy bookmarks (outline) to the output.
  234.     Trailer /Root oget /Outlines knownoget {
  235.       /First knownoget {
  236.     { dup writeoutline /Next knownoget not { exit } if } loop
  237.       } if
  238.     } if
  239.   } if        % end .writepdfmarks
  240.   currentdict end
  241. } bind def
  242. /pdfopencache {        % - pdfopencache -
  243.     % Create and initialize some caches.
  244.   /PageCount pdfpagecount def
  245.   /PageNumbers PageCount 65534 .min dict def
  246.   /PageIndex PageCount 65534 .min array def
  247. } bind def
  248. /pdfopenfile {        % <file> pdfopenfile <dict>
  249.    pdfdict readonly pop        % can't do it any earlier than this
  250.    15 dict begin
  251.    /LocalResources 0 dict def
  252.    /DefaultMatrix null def    % establish binding
  253.    /Printed where { pop } {
  254.         % Guess whether the output device is a printer.
  255.      /Printed currentpagedevice /OutputFile known def
  256.    } ifelse
  257.    /PSLevel1 where { pop } { /PSLevel1 false def } ifelse
  258.    cvlit /PDFfile exch def
  259.    /PDFsource PDFfile def
  260.    /Repaired false def
  261.    PDFfile dup 0 setfileposition pdfstring readstring 
  262.    not {/pdfopen cvx /syntaxerror signalerror} if
  263.    (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
  264.    length /PDFoffset exch def pop cvr /PDFversion exch def
  265.    findxref
  266.    initPDFobjects
  267.     % Read the last cross-reference table.
  268.    readxref /Trailer exch def
  269.    Trailer /Encrypt known
  270.     { pdf_process_Encrypt    % signal error
  271.     }
  272.    if
  273.     % Read any previous cross-reference tables.
  274.    Trailer { /Prev .knownget not { exit } if readxref } loop
  275.    Repaired { printrepaired } if
  276.    currentdict end
  277.  } bind def
  278.  
  279. % Skip backward over the %%EOF at the end of the PDF file, and read
  280. % the preceding startxref line.  The PDF specification unambiguously
  281. % requires that the %%EOF appear on a line by itself, and that the
  282. % startxref and the following position value appear on separate lines;
  283. % however, some applications (including, apparently, Acrobat Distiller
  284. % on the Macintosh) may add up to 2K of garbage after the %%EOF, and some
  285. % other applications also truncate the %%EOF to %%EO, and/or put the
  286. % startxref and the following value on the same line.
  287. % A file reported from Distiller 3.02b for AIX 4.1.1 has 2076 bytes
  288. % of garbage. The tolerance is increased to 4K to cover future
  289. % applications and bigger allocation units.
  290. /findxref {        % - findxref <xrefpos>
  291.   PDFfile dup dup 0 setfileposition bytesavailable
  292.   dup /PDFfilelen exch def
  293.     % Find the last %%EOF string (within 4096 bytes)
  294.   4096 sub PDFoffset .max
  295.   2 copy setfileposition
  296.   PDFfilelen exch sub string 1 index exch readstring pop {
  297.     (\015%%EO) search {        % Adobe can handle truncated key string
  298.       pop pop            % if found, keep searching 'post' string
  299.     } {
  300.       (\012%%EO) search
  301.     { pop pop } { exit } ifelse    % exit if neither string found
  302.     } ifelse
  303.   } loop
  304.   PDFfilelen exch length sub 4 sub PDFoffset .max exch 1 index setfileposition
  305.     % Stack: eofpos
  306.     % Check for whether this is, in fact, a valid PDF file.
  307.  
  308.     % (ATAPY changes) %%EOF may not be followed by end_of_line symbol
  309.  
  310.   dup PDFfilelen exch sub dup dup 7 gt exch 5 lt or {
  311.     pop true
  312.   } {
  313.     string PDFfile exch readstring pop
  314.     dup (%%EOF) eq exch 
  315.     dup (%%EOF\n) eq exch dup (%%EOF\r) eq
  316.     exch (%%EOF\r\n) eq or or or not
  317.  
  318.     % (End of ATAPY changes)
  319.   
  320.   } ifelse {
  321.     (
  322.    **** This file has a corrupted %%EOF marker, or garbage after the %%EOF.
  323. ) pdfformaterror
  324.   } if
  325.   PDFfile exch setfileposition
  326.     % Now read the startxref and xref start position.
  327.   prevline token not { null } if dup type /integertype eq {
  328.     exch pop cvi        % xref start position
  329.     exch PDFfile exch setfileposition
  330.     prevline (startxref) linene { /findxref cvx /syntaxerror signalerror } if
  331.     pop
  332.   } {    % else, this file has 'startxref #####' format
  333.     (startxref) ne { /findxref cvx /syntaxerror signalerror } if
  334.     cvi        % xref start position
  335.     (
  336.    **** The format of the startxref line in this file is invalid.
  337. ) pdfformaterror
  338.     exch PDFfile exch setfileposition
  339.   } ifelse
  340. } bind def
  341. /stderrfile (%stderr) (w) file def
  342. /stderrprint {                % <string> stderrprint -
  343.   //stderrfile dup 3 -1 roll writestring flushfile
  344. } bind def
  345. /pdfformaterror {    % <string> pdfformaterror -
  346.   stderrprint
  347.   /Repaired true store
  348. } bind def
  349. /printrepaired {
  350.   Trailer /Info knownoget {
  351.     /Producer knownoget not { null } if
  352.   } {
  353.     null
  354.   } ifelse
  355.   dup null eq {
  356.     pop (\
  357.    **** Please notify the author of the software that produced this file
  358. )
  359.   } {
  360.     (   **** The file was produced by ) stderrprint
  361.     % Handle a Unicode Producer.
  362.     (\376\377) anchorsearch {
  363.       pop dup length 2 idiv string 0 1 2 index length 1 sub {
  364.         % Stack: origstr newstr i
  365.     1 index exch 3 index 1 index 2 mul 1 add get put
  366.       } for exch pop
  367.     } if
  368.     stderrprint
  369.     (:
  370.    **** please notify the author of this software
  371. )
  372.   } ifelse stderrprint
  373. (\
  374.    **** that the file does not conform to Adobe's published PDF
  375.    **** specification.  Processing of the file will continue normally.
  376.  
  377. ) stderrprint
  378. } bind def
  379.  
  380. % Write the outline structure for a file.  Uses linkdest (below).
  381. /writeoutline        % <outlinedict> writeoutline -
  382.  { mark
  383.    0 2 index /First knownoget
  384.     { { exch 1 add exch /Next knownoget not { exit } if } loop }
  385.    if
  386.         % stack: dict mark count
  387.    dup 0 eq
  388.     { pop 1 index
  389.     }
  390.     { 2 index /Count knownoget { 0 lt { neg } if } if
  391.       /Count exch 3 index
  392.     }
  393.    ifelse linkdest /Title oget /Title exch /OUT pdfmark
  394.    /First knownoget
  395.     { { dup writeoutline /Next knownoget not { exit } if } loop }
  396.    if
  397.  } bind def
  398.  
  399. % Close a PDF file.
  400. /pdfclose        % <dict> pdfclose -
  401.  { begin
  402.    PDFfile closefile
  403.    end
  404.  } bind def
  405.  
  406. % ======================== Page accessing ======================== %
  407.  
  408. % Get a (possibly inherited) attribute of a page.
  409. /pget            % <pagedict> <key> pget <value> -true-
  410.             % <pagedict> <key> pget -false-
  411.  { 2 copy knownoget
  412.     { exch pop exch pop true
  413.     }
  414.     { exch /Parent knownoget
  415.        { exch pget }
  416.        { pop false }
  417.       ifelse
  418.     }
  419.    ifelse
  420.  } bind def
  421.  
  422. % Get the value of a resource on a given page.
  423. /rget {            % <resname> <pagedict> <restype> rget <value> -true-
  424.             % <resname> <pagedict> <restype> rget -false-
  425.   LocalResources 1 index knownoget {
  426.      3 index knownoget
  427.   } {
  428.     false
  429.   } ifelse {
  430.     exch pop exch pop exch pop true
  431.   } {
  432.     exch /Resources pget {
  433.       exch knownoget { exch knownoget } { pop false } ifelse
  434.     } {
  435.       pop pop false
  436.     } ifelse
  437.   } ifelse
  438. } bind def
  439.  
  440. % Get the total number of pages in the document.
  441. /pdfpagecount        % - pdfpagecount <int>
  442.  { Trailer /Root oget /Pages oget /Count oget
  443.  } bind def
  444.  
  445. % Find the N'th page of the document by iterating through the Pages tree.
  446. % The first page is numbered 1.
  447. /pdffindpageref {        % <int> pdffindpage <objref>
  448.   dup Trailer /Root oget /Pages get
  449.     {        % We should be able to tell when we reach a leaf
  450.         % by finding a Type unequal to /Pages.  Unfortunately,
  451.         % some files distributed by Adobe lack the Type key
  452.         % in some of the Pages nodes!  Instead, we check for Kids.
  453.       dup oforce /Kids knownoget not { exit } if
  454.       exch pop null
  455.       0 1 3 index length 1 sub {
  456.          2 index exch get
  457.      dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
  458.         % Stack: index kids null noderef count
  459.      dup 5 index ge { pop exch pop exit } if
  460.      5 -1 roll exch sub 4 1 roll pop
  461.       } for exch pop
  462.         % Stack: index null|noderef
  463.       dup null eq { pop pop 1 null exit } if
  464.     } loop
  465.         % Stack: index countleft noderef
  466.    1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
  467.    exch pop
  468.    PageIndex 2 index 1 sub 65533 .min 2 index oforce put
  469.    PageNumbers 1 index oforce 3 index dup 65534 le
  470.     { put }
  471.     { pop pop pop }    % don't store more than 65534 pagenumbers
  472.    ifelse
  473.    exch pop
  474. } bind def
  475. /pdffindpage {        % <int> pdffindpage <pagedict>
  476.   pdffindpageref oforce
  477. } bind def
  478.  
  479. % Find the N'th page of the document.
  480. % The first page is numbered 1.
  481. /pdfgetpage        % <int> pdfgetpage <pagedict>
  482.  { PageIndex 1 index 1 sub dup 65533 lt
  483.     { get }
  484.     { pop pop null }
  485.    ifelse
  486.    dup null ne
  487.     { exch pop oforce }
  488.     { pop pdffindpage }
  489.    ifelse
  490.  } bind def
  491.  
  492. % Find the page number of a page object (inverse of pdfgetpage).
  493. /pdfpagenumber        % <pagedict> pdfpagenumber <int>
  494.  {    % We use the simplest and stupidest of all possible algorithms....
  495.    PageNumbers 1 index .knownget
  496.     { exch pop
  497.     }
  498.     { 1 1 PageCount 1 add    % will give a rangecheck if not found
  499.        { dup pdfgetpage oforce 2 index eq { exit } if pop
  500.        }
  501.       for exch pop
  502.     }
  503.    ifelse
  504.  } bind def
  505.  
  506. % Display a given page.
  507. /boxrect        % [<llx> <lly> <urx> <ury>] boxrect <x> <y> <w> <h>
  508.  { aload pop exch 3 index sub exch 2 index sub
  509.  } bind def
  510. /resolvedest {        % <name|string|other> resolvedest <other|null>
  511.   dup type /nametype eq {
  512.     Trailer /Root oget /Dests knownoget {
  513.       exch knownoget not { null } if
  514.     } {
  515.       null
  516.     } ifelse
  517.   } {
  518.     dup type /stringtype eq {
  519.       Trailer /Root oget /Names knownoget {
  520.     /Dests knownoget {
  521.       exch nameoget
  522.     } {
  523.       pop null
  524.     } ifelse
  525.       } {
  526.     pop null
  527.       } ifelse
  528.     } if
  529.   } ifelse
  530. } bind def
  531. /linkdest {        % <link|outline> linkdest
  532.             %   ([/Page <n>] /View <view> | ) <link|outline>
  533.   dup /Dest knownoget
  534.     { resolvedest
  535.       dup type /dicttype eq { /D knownoget not { null } if } if
  536.       dup null eq
  537.        { pop }
  538.        { dup 0 oget
  539.      dup null eq
  540.       { pop }
  541.       { dup type /integertype ne { pdfpagenumber } if
  542.         /Page exch 4 -2 roll
  543.       }
  544.      ifelse
  545.      dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
  546.        }
  547.       ifelse
  548.     }
  549.    if
  550. } bind def
  551. % <pagedict> mark ... -proc- -
  552. /namedactions 8 dict dup begin
  553.   /FirstPage {
  554.     /Page 1 3 -1 roll
  555.   } def
  556.   /LastPage {
  557.     counttomark 2 add index pdfpagecount /Page exch 3 -1 roll
  558.   } def
  559.   /NextPage {
  560.     counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll
  561.   } def
  562.   /PrevPage {
  563.     counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll
  564.   } def
  565. end readonly def
  566. % <pagedict> <annotdict> -proc- -
  567. /annottypes 5 dict dup begin
  568.   /Text {
  569.     mark exch
  570.      { /Rect /Open /Contents }
  571.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  572.     forall pop /ANN pdfmark
  573.   } bind def
  574.   /Link {
  575.     mark exch
  576.      { /Rect /Border }
  577.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  578.     forall dup /A knownoget {
  579.       dup /URI known {
  580.         /A mark 3 2 roll    % <<>> /A [ <<action>>
  581.         { oforce } forall
  582.         .dicttomark
  583.         3 2 roll
  584.       } {
  585.         dup /D knownoget {
  586.       exch pop exch dup length dict copy dup /Dest 4 -1 roll put
  587.         } {
  588.       /N knownoget {        % Assume /S /Named
  589.          namedactions exch .knownget { exec } if
  590.       } if
  591.         } ifelse
  592.       } ifelse
  593.     } if
  594.     linkdest pop /LNK pdfmark
  595.   } bind def
  596. end readonly def
  597.  
  598. /pdfshowpage        % <pagedict> pdfshowpage -
  599.  { dup /Page exch store
  600.    pdfshowpage_init 
  601.    pdfshowpage_setpage 
  602.    save /PDFSave exch store
  603.    (before exec) VMDEBUG
  604.      pdfshowpage_finish
  605.    (after exec) VMDEBUG
  606.    PDFSave restore
  607.  } bind def
  608.  
  609. /pdfpagecontents    % <pagedict> pdfpagecontents <contents>
  610.  { } bind def
  611.  
  612. /pdfshowpage_init     % <pagedict> pdfshowpage_init <pagedict>
  613.  { /DSCPageCount DSCPageCount 1 add store
  614.  } bind def
  615.  
  616. /.pdfshowpage_Install {    % <pagedict> [<prevproc>] .pdfshowpage_Install -
  617.   exch
  618.     % We would like to clip to the CropBox here, but the subsequent
  619.     % initgraphics would override it.  Instead, we have to handle it
  620.     % in graphicsbeginpage.
  621.   dup /MediaBox pget {
  622.     dup 0 get neg exch 1 get neg translate
  623.   } if
  624.   pop 0 get exec
  625. } bind def
  626.  
  627. /pdfshowpage_setpage {    % <pagedict> pdfshowpage_setpage <pagedict>
  628.   4 dict begin        % for setpagedevice
  629.     % Stack: pagedict
  630.   currentpagedevice /Orientation 2 index /Rotate pget not { 0 } if 90 idiv
  631.     % Rotate specifies *clockwise* rotation!
  632.     neg 3 and def
  633.     % Stack: pagedict currentpagedict
  634.   1 index /MediaBox pget {
  635.             % Set the page size.
  636.     boxrect 2 array astore /PageSize exch def pop pop
  637.   } if
  638.   dup /Install .knownget {
  639.             % Don't let the Install procedure get more deeply
  640.             % nested after every page.
  641.       dup type dup /arraytype eq exch /packedarraytype eq or {
  642.     dup length 4 eq {
  643.       dup 2 get /.pdfshowpage_Install load eq {
  644.         1 get 0 get    % previous procedure
  645.       } if
  646.     } if
  647.       } if
  648.   } {
  649.     { }
  650.   } ifelse 1 array astore
  651.   2 index exch /.pdfshowpage_Install load /exec load
  652.   4 packedarray cvx
  653.     % Stack: pagedict currentpagedict installproc
  654.   /Install exch def
  655.     % Stack: pagedict currentpagedict
  656.   pop currentdict end setpagedevice
  657. } bind def
  658.  
  659. /pdfshowpage_finish {    % <pagedict> pdfshowpage_finish -
  660.  
  661.   .writepdfmarks {
  662.  
  663.     % Copy the crop box.
  664.     dup /CropBox knownoget {
  665.     % If the page has been rotated, rotate the CropBox.
  666.       mark /CropBox 3 -1 roll
  667.       3 index /Rotate pget {
  668.     90 idiv 1 and 0 ne {
  669.       aload pop 4 -2 roll exch 4 2 roll exch 4 array astore
  670.     } if
  671.       } if
  672.       /PAGE pdfmark
  673.     } if
  674.  
  675.     % Copy annotations and links.
  676.     dup /Annots knownoget {
  677.       0 1 2 index length 1 sub
  678.        { 1 index exch oget
  679.          dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
  680.        }
  681.       for pop
  682.     } if
  683.  
  684.   } if        % end .writepdfmarks
  685.  
  686.     % Display the actual page contents.
  687.    6 dict begin
  688.    /BXlevel 0 def
  689.    /BGDefault currentblackgeneration def
  690.    /UCRDefault currentundercolorremoval def
  691.     %****** DOESN'T HANDLE COLOR TRANSFER YET ******
  692.    /TRDefault currenttransfer def
  693.   matrix currentmatrix 2 dict
  694.   2 index /CropBox knownoget {
  695.     boxrect 4 array astore 1 index /ClipRect 3 -1 roll put
  696.   } if
  697.   dictbeginpage /DefaultMatrix 1 index store setmatrix
  698.   dup          % for showing annotations below
  699.   count /pdfemptycount exch store
  700.   gsave
  701.     % If the page uses any transparency features, show it within
  702.     % a transparency group.
  703.   PDFversion 1.4 lt {
  704.     showpagecontents
  705.   } {
  706.     dup pageusestransparency {
  707.       % Show the page within a PDF 1.4 device filter.
  708.       0 .pushpdf14devicefilter {
  709.     % If the page has a Group, enclose contents in transparency group.
  710.         % (Adobe Tech Note 5407, sec 9.2)
  711.         dup /Group knownoget {
  712.       1 index /CropBox knownoget not {
  713.         1 index /MediaBox oget
  714.       } if .beginformgroup {
  715.         showpagecontents
  716.       } .internalstopped {
  717.         .discardtransparencygroup stop
  718.       } if .endtransparencygroup
  719.         } {
  720.       showpagecontents
  721.         } ifelse
  722.       } .internalstopped {
  723.     % todo: discard
  724.     .popdevicefilter stop
  725.       } if .popdevicefilter
  726.     } {
  727.       showpagecontents
  728.     } ifelse
  729.   } ifelse
  730.   grestore
  731.    % todo: mixing drawing ops outside the device filter could cause
  732.    % problems, for example with the pnga device.
  733.    /Annots knownoget { { oforce drawannot } forall } if
  734.    endpage
  735.    end            % scratch dict
  736. } bind def
  737. /showpagecontents {    % <pagedict> showpagecontents -
  738.   /Contents knownoget not { 0 array } if
  739.   dup type /arraytype ne { 1 array astore } if {
  740.     oforce false resolvestream pdfopdict .pdfrun
  741.   } forall
  742. } bind def
  743. /processcolorspace {    % - processcolorspace <colorspace>
  744.     % The following is per the PLRM3.
  745.   currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
  746.   exch pop exch pop
  747.   dup type /nametype ne { cvn } if
  748.   dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
  749. } bind def
  750.  
  751. % ------ Transparency support ------ %
  752.  
  753. % Determine whether a page might invoke any transparency features:
  754. %    - Group in the page dictionary
  755. %    - Non-default ca, CA, or SMask in an ExtGState
  756. %    - Form XObject with Group
  757. %    - Image XObject with SMask
  758. % ****** DO WE NEED TO LOOK IN RESOURCE DICTS OF OTHER CONTENT STREAMS? ******
  759. /pageusestransparency {        % <pagedict> pageusestransparency <bool>
  760.   PDFversion 1.4 lt {
  761.     pop false
  762.   } {
  763.     dup /Group known {
  764.       pop true
  765.     } {
  766.       false exch {
  767.     dup resourceusestransparency { pop not exit } if
  768.     /Parent knownoget not { exit } if
  769.       } loop
  770.     } ifelse
  771.   } ifelse
  772. } bind def
  773. % Check the Resources of a page or Form.
  774. /resourceusestransparency {    % <dict> resourceusestransparency <bool>
  775.   {    % Use loop to provide an exitable context.
  776.     /Resources knownoget not { 0 dict } if
  777.     dup /ExtGState knownoget {
  778.       false exch {
  779.     exch pop oforce
  780.     dup /ca knownoget { 1 ne { pop not exit } if } if
  781.     dup /CA knownoget { 1 ne { pop not exit } if } if
  782.     dup /SMask knownoget { /None ne { pop not exit } if } if
  783.     pop
  784.       } forall { pop true exit } if
  785.     } if
  786.     dup /XObject knownoget {
  787.       false exch {
  788.     exch pop oforce dup /Subtype get
  789.     dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
  790.     /Form eq {
  791.       dup /Group known { pop not exit } if
  792.       resourceusestransparency { not exit } if
  793.     } {
  794.       pop
  795.     } ifelse
  796.       } forall { pop true exit } if
  797.     } if
  798.     pop false exit
  799.   } loop
  800. } bind def
  801.  
  802. end            % pdfdict
  803. .setglobal
  804.